#ifndef VIA_VIAWIN_H__
#define VIA_VIAWIN_H__

#include <windows.h>
#include <tchar.h>
#include <process.h>

#include "commands.h"
#include "viaimg.h"

#ifdef __cplusplus
extern "C" {
#endif
	
	LRESULT CALLBACK CViaWin_WndProc (HWND, UINT, WPARAM, LPARAM) ;
	DWORD WINAPI viaDialog_Thread(PVOID pParm);
	
#ifdef __cplusplus
}
#endif

namespace nVIA {
	class CGui;
	class CWin;
	class CData;

// 	CData**	GetTlsDataEx();
// 	CData**	GetTlsData();
}

/********************************************************************
 * CData
 * Responsible for return value or data to CViaWin_WndProc according 
 * to user's input.
 * Related to thread local storage index g_dwViaTlsIndex and 
 * used by CViaWin_WndProc.
 ********************************************************************/

class nVIA::CData {
public:
	CData() { reset(); }
	CData(HANDLE hViaCommands) { 
		reset();
		m_pBitmap = NULL;
		Init(hViaCommands); 
	}
	~CData() {Release();}

	//void	SetViaCommands(HANDLE hViaCommands);
	BOOL	Init(HANDLE hViaCommands) {
		reset();
		Release();
		m_hViaCommands = hViaCommands;
		return TRUE;
	}
	void	Release() {
		if (m_pBitmap) {
			delete m_pBitmap;
			m_pBitmap = NULL;
		}
	}
	BOOL	SetWidth(char* expression) {
		return getValue(expression, &m_width);
	}
	BOOL	SetHeight(char* expression) {
		return getValue(expression, &m_height);
	}
	BOOL	SetPitch(char* expression) {
		return getValue(expression, &m_pitch);
	}
	BOOL	SetBits(char* expression) {
		return getPointer(expression, &m_bits);
	}
	void	SetForamt(VIA_COLORFORMAT format) { m_format = format; }
	int		GetWidth() {return m_width;}
	int		GetHeight() {return m_height;}
	int		GetPitch() {return m_pitch;}
	PBYTE	GetBits() {
		if (m_bHasImage)
			return m_pBitmap->Bits();
		return NULL;
	}
	BITMAPINFO*	GetInfo() {
		if (m_bHasImage)
			return m_pBitmap->Info();
		return NULL;
	}

	BOOL	UpdateData();
	//void	SetWin(nVIA::CWin* pwin) { m_pWin = pwin; }
	//CWin*	GetWin() { return m_pWin; }

protected:
	BOOL	getValue(char* expression, long* value);
	BOOL	getPointer(char* expression, PBYTE* pt);
	void	reset() {
		m_width = 0;
		m_height = 0;
		m_pitch = 0;
		m_bits = NULL;
		m_bHasImage = FALSE;
	}

protected:
	HANDLE			m_hViaCommands;
	nVIA::CBitmap*	m_pBitmap;
	//nVIA::CWin*		m_pWin;

private:
	long	m_width;
	long	m_height;
	long	m_pitch;
	VIA_COLORFORMAT m_format;
	BYTE*	m_bits;
	BOOL	m_bHasImage;
}; 

/******************************
 * CGui
 * Manage windows,
 ******************************/

#define VIA_DIALOG_MAX_NUM 16

class nVIA::CGui {
public:
	CGui(HINSTANCE hInstance, HANDLE hViaCommands);
	~CGui();

	int		Create(HINSTANCE hInstance, HANDLE hViaCommands);
	void	Release();
	int		Dialog();
	
	TCHAR*		GetAppName() const { return m_szAppName; }
	HINSTANCE	GetInstance() const {return m_hInstance;}
	HANDLE		GetViaCommands() const { return m_hViaCommands; }
	
private:
	ATOM	RegisterClass();

protected:
	HINSTANCE		m_hInstance;
	WNDCLASSEX		m_wndclass;
	
	HANDLE			m_hViaCommands;	// pointer to vs/ds application
	nVIA::CWin*		m_lstWin[VIA_DIALOG_MAX_NUM];	// TODO replace with std::list
	int				m_nWin;
	ATOM			m_WndClass;

protected:
	static TCHAR*	m_szAppName;
	static WNDPROC	m_wndProc;
};


/******************************
 * CWin
 * Display VC Image Assist GUI
 ******************************/
#define CHILD_WND_NUM	(10)
#define	EDIT_LINE_NUM	(1024)

#define ID_STATIC_TOOLBOX	(9)
#define ID_STATIC_WIDTH		(8)
#define ID_STATIC_HEIGHT	(7)
#define ID_STATIC_DATA		(6)
#define ID_STATIC_PITCH		(5)
#define ID_EDIT_DATA		(0)
#define	ID_EDIT_WIDTH		(1)
#define	ID_EDIT_HEIGHT		(2)
#define	ID_EDIT_PITCH		(3)

class nVIA::CWin {
public:
	//CWin();
	CWin(CGui* pGui);
	//CWin(szAppName, char* szPrjName);
	~CWin() {Release();}

	int		Create();
	//int		Create(char* szAppName, char* szPrjName);
	void	Run();
	void	Release();
	//todo how to implement it
	//void	CloseThread();

	HANDLE	GetCommands() const { return m_pGui->GetViaCommands(); }
	HWND	GetWnd() const { return m_hWnd; }
	TCHAR*	GetAppName() const { return m_pGui->GetAppName(); }
	HINSTANCE	GetInstance() const { return m_pGui->GetInstance(); }
	CData*	GetData() { return m_pData; }
	BOOL	IsDestoyed() { 
		if (!m_hWnd) 
			return TRUE; 
		return FALSE;
	}

public:
	void	GetMetric();
	void	GetChildPos(RECT* prt);
	void	DestroyWnd();
	BOOL	UpdateData();

	BOOL	OnCreate(HWND hWnd);
	BOOL	OnSize(RECT* prt);
	BOOL	OnToolbar(int nWndId, int nNotify, HWND hWnd);
	BOOL	OnLButtonDown(int nNotify, int x, int y);
	BOOL	OnPaint();
	BOOL	OnDestroy();

public:
	ULONG	m_threadID;
	HANDLE	m_thread;

protected:
	const nVIA::CGui*	m_pGui;
	HWND	m_hWnd;
	CData*	m_pData;

private:
	// toolbox
	HWND	m_hChildWnds[CHILD_WND_NUM];
	int		m_nToolbarHeight;
	int		m_nChildWndsWidth[CHILD_WND_NUM];
	POINT	m_ptChildWndsPos[CHILD_WND_NUM];
	TCHAR	m_szEdit[4][EDIT_LINE_NUM];
	int		m_StatusEdit[4];

	// image
	BOOL	m_bDataDirty;
	BOOL	m_bSync;
};



#endif//VIA_VIAWIN_H__